/*
 * hapfile.h
 *
 *  Created on: Jul 28, 2010
 *      Author: Pierre Lindenbaum PhD
 *              plindenbaum@yahoo.fr
 *              http://plindenbaum.blogspot.com
 *              
 */
#ifndef TRANS_MARKERS_H
#define TRANS_MARKERS_H
#include <iostream>
#include <vector>
#include "core/io/gzstreambuf.h"
#include "core/util/tokenizer.h"
#include "marker.h"

class MarkerList
    {
    private:
	MarkerList(const MarkerList& cp)
	    {

	    }

    protected:
	ChromosomePtr _chrom;
	std::vector<MarkerPtr> markers;
	MarkerList(const ChromosomePtr chrom):_chrom(chrom)
	    {

	    }

    public:
	typedef int size_type;

	virtual ~MarkerList()
	    {
	    while(!markers.empty())
		{
		delete markers.back();
		markers.pop_back();
		}
	    }


	const ChromosomePtr chrom() const
	    {
	    return _chrom;
	    }

	size_type size() const
	    {
	    return (size_type)markers.size();
	    }

	const MarkerPtr at(size_type i) const
	    {
	    return markers.at((std::vector<MarkerPtr>::size_type)i);
	    }
	const MarkerPtr operator[](size_type i) const
	    {
	    return at(i);
	    }

	friend std::ostream& operator << (std::ostream& out,const MarkerList& o);
	friend class MarkerListFactory;
    };

std::ostream& operator << (std::ostream& out,const MarkerList& o)
   {
    out << *(o.chrom())<<" n=" << o.size();
   return out;
   }

typedef MarkerList* MarkerListPtr;



class MarkerListFactory
    {
    private:
	    void crlf(std::string& line)
		{
		if(!line.empty() && line.at(line.size()-1)=='\r')
	    		{
	    		line.erase(line.size()-1,1);
	    		}
		}
    public:
	MarkerListFactory()
	    {
	    }
	~MarkerListFactory()
	    {
	    }

	MarkerListPtr parse(const char* filename,const ChromosomePtr chrom)
	    {
	    MarkerListPtr list= new MarkerList(chrom);

	    u915::io::gzinbuf buff(filename,100000);
	    std::iostream in(&buff);
	    std::string line;

	    if(!std::getline(in,line,'\n'))
		{
		delete list;
		std::ostringstream os;
		os << "cannot read first line of "<< filename;
		throw std::runtime_error(os.str());
		}

	    crlf(line);


	    if(line.compare("rsID position a0 a1")!=0)
		{
		delete list;
		std::ostringstream os;
		os << "first line of "<< filename << " is not \"rsID position a0 a1\" but \""
			<< line << "\"";
		for(int i=0;i< line.size();++i)
		    {
		    if(line[i]=='\r') os << "NOOOO";
		    os << line[i];
		    }
		throw std::runtime_error(os.str());
		}

	    while(std::getline(in,line))
	   	{
		crlf(line);
	   	u915::util::Tokenizer tokens(line,' ');
	   	if(tokens.size()!=4)
	   	    {
		    delete list;
		    std::ostringstream os;
		    os << "Expected 4 tokens in "<< line << "but got " << tokens;
		    throw std::runtime_error(os.str());
	   	    }
	   	char *endptr;
	   	int64_t position=std::strtol(tokens[1].c_str(),&endptr,10);
	   	if(*endptr!=0 || position==0)
	   	    {
	   	    delete list;
		    std::ostringstream os;
		    os << "Bad position in "<< line;
		    if(endptr!=0) os << " endptr=\""<< endptr << "\"";
		    throw std::runtime_error(os.str());
	   	    }

	   	if(tokens[2].size()!=1 || tokens[3].size()!=1)
	   	    {
	   	    delete list;
		    std::ostringstream os;
		    os << "Bad bases A1/A2 in "<< line;
		    throw std::runtime_error(os.str());
	   	    }

	   	MarkerPtr m=new Marker(
	   		tokens[0],
	   		chrom,
	   		position,
	   		tokens[2].at(0),
	   		tokens[3].at(0)
	   		);
	   	list->markers.push_back(m);
	   	}
	    return list;
	    }
    };

#endif
